package com.admin.config.security.oa2.basicCircuit.authorization.security.authorizationConfig;

import com.admin.config.security.oa2.basicCircuit.authorization.tokenConverter.SubjectAttributeUserTokenConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.provider.token.DefaultAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;

import javax.sql.DataSource;
import java.security.KeyPair;

/**
 * Authorization 的 clientId：secret 登陸
 * 用 最終用戶密碼賬戶 為參數 訪問 稱爲 密碼模式
 * 返回結果
 * {
 *     "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9
 *     .eyJzdWIiOiJzdWJqZWN0IiwiZXhwIjoyMTY2MjM0MTc2LCJhdXRob3JpdGllcyI6WyJVU0VSIl0sImp0aSI6IjAzYjYyMGUwLWExZWUtNDY0MS05ZjM3LTQ5YjJhYjYxYjZhMCIsImNsaWVudF9pZCI6InJlYWRlciIsInNjb3BlIjpbIm1lc3NhZ2U6cmVhZCJdfQ.QdAdGSiFX5j9s3DzPnrIPt-Vdwy73Kh7JJQheu0V_DkkdpSzufccIn_Na-SkoMJjhltLzwLLu5H-TvD72OuhgQQwpXaQIoyzFkrMHJijNljPIaBaQbaE5PW5meU6V9uMOlxy4OUuZC1YDDD9MIdGqiq0eG_BiubVZlN93992fD7mNHBfAnCO-b8sWwxoHi4FZmw1PNc_bRVE6cQjz2xxC15ee6dmU55zQIjOtQbyKiEDvyM_CkQ3kplPyikWyOhtH3SdLe1MKK3ydWJO5GYZmGy7sUJrDU_ozW12gdNcSTW6OKJEjK8Vj39YDZXCL5TGwiKmFTMeNDmxn2YaTyQ0zA",
 *     "token_type": "bearer",
 *     "expires_in": 599999999,
 *     "scope": "message:read",
 *     "jti": "03b620e0-a1ee-4641-9f37-49b2ab61b6a0"
 * }
 */
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {

    private DataSource dataSource;
    private AuthenticationManager authenticationManager;
    private KeyPair keyPair;
    private PasswordEncoder passwordEncoder;

    public AuthorizationServerConfiguration(
            DataSource dataSource,
            AuthenticationConfiguration authenticationConfiguration,
            KeyPair keyPair,
            PasswordEncoder passwordEncoder) throws Exception {
        this.dataSource = dataSource;
        this.authenticationManager = authenticationConfiguration.getAuthenticationManager();
        this.keyPair = keyPair;
        this.passwordEncoder = passwordEncoder;
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients)
            throws Exception {
        // @formatter:off

        clients.inMemory()
                .withClient("reader")
                .authorizedGrantTypes("password")
                .secret(passwordEncoder.encode("secret"))
//                .secret("{noop}secret")
                .scopes("message:read")
                .accessTokenValiditySeconds(600_000_000);
//        clients.inMemory()
//                .withClient("reader")
//                .authorizedGrantTypes("password")
//                .secret("{noop}secret")
//                .scopes("message:read")
//                .accessTokenValiditySeconds(600_000_000)
//                .and()
//                .withClient("writer")
//                .authorizedGrantTypes("password")
//                .secret("{noop}secret")
//                .scopes("message:write")
//                .accessTokenValiditySeconds(600_000_000)
//                .and()
//                .withClient("noscopes")
//                .authorizedGrantTypes("password")
//                .secret("{noop}secret")
//                .scopes("none")
//                .accessTokenValiditySeconds(600_000_000);
        // @formatter:on
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        // @formatter:off
        endpoints
                .authenticationManager(this.authenticationManager)
                .tokenStore(tokenStore())
                .accessTokenConverter(accessTokenConverter());
    }

    @Bean
    public JwtAccessTokenConverter accessTokenConverter() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        converter.setKeyPair(this.keyPair);

        DefaultAccessTokenConverter accessTokenConverter = new DefaultAccessTokenConverter();
        accessTokenConverter.setUserTokenConverter(new SubjectAttributeUserTokenConverter());
        converter.setAccessTokenConverter(accessTokenConverter);

        return converter;
    }

    @Bean
    public TokenStore tokenStore() {
        return new JwtTokenStore(accessTokenConverter());
    }


}
